<?php
declare (strict_types = 1);

namespace app\model;

use app\constant\CommonConstant;
use app\constant\ModelConstant;
use Carbon\Carbon;
use think\facade\Cache;
use think\helper\Arr;
use think\Model;
use think\Request;

/**
 * @property string $ip
 * @property integer $event_type
 * @property string $created_at
 * @property array $params
 * @property integer $user_agent
 * @property integer $is_track
 * @property string $trace_id
 * @property string $fbc_at
 * @property string $fbclid
 * @property string $pixel_id
 * @property array $response
 * @property string $website
 * @property integer $pid
 * @property string $shop_code
 * @property integer $platform
 */
class PixelLogs extends Model
{
    public $autoWriteTimestamp = false;
    protected $field = [
        'params','ip','user_agent','is_track','trace_id','event_type',
        'created_at','fbc_at','fbclid','pixel_id','response','website',
        'pid','product_id','order_id','platform','shop_code'
    ];

    protected $json = ['params','response'];
    protected $jsonAssoc = true;

    public static function createTrackLog(array $request): PixelLogs | null
    {
        $event_type = Arr::get($request,'event_type', CommonConstant::FB_EVENT_PREVIEW);
        $ip = Arr::get($request,'ip');
        $product_id = Arr::get($request,'product_id','');
        $orderId = Arr::get($request,'order_id',0);
        if($event_type == CommonConstant::FB_EVENT_PREVIEW){
            $redis = Cache::store('redis');
            $cnTime = Carbon::now();
            // 生成唯一的Redis键（按平台、商品和日期区分）
            // "pixellog:{Arr}:" . $cnTime->toDateString() . ":{$product_id}"
            $redisKey = sprintf("pixelLog:%s:%s:%s",Arr::get($request,'shop_code'),$cnTime->format("Ymd"),$product_id);
            //Redis::expire($redisKey, 86400); // 设置键过期时间
            // 检查IP是否已在Redis集合中
            if ($redis->sismember($redisKey, $ip)) {
                return null; // IP已存在，直接跳过
            }
            // 确定美国时间的当天范围
            $startOfDayUS = $cnTime->copy()->startOfDay()->toDateTimeString();
            $endOfDayUS = $cnTime->copy()->endOfDay()->toDateTimeString();

            // 查询数据库确认是否存在
            $lprows = self::where('event_type', CommonConstant::FB_EVENT_PREVIEW)
                ->where('ip', $ip)
                ->where("product_id", $product_id)
                ->whereBetween("created_at", [$startOfDayUS, $endOfDayUS])
                ->findOrEmpty();

            if ($lprows->isExists()) {
                // 数据库中存在：异步写回Redis（避免阻塞当前请求）
                $redis->sadd($redisKey, $ip); // 加入集合
                return null;
            }

            // 创建新记录并原子性加入Redis集合
            $added = $redis->sadd($redisKey, $ip);
            if ($added === 0) {
                return null; // 并发请求已添加，放弃创建
            }

            // 首次创建时设置过期时间（避免遗漏）
            if ($redis->sCard($redisKey) === 1) {
                $redis->expire($redisKey, 86400);
            }
        }else{
            $row = self::where('order_id',$orderId)
                ->where('event_type',CommonConstant::FB_EVENT_PURCHASE)
                ->when($shop_code = Arr::get($request,'shop_code',''), function ($query) use ($shop_code) {
                    $query->where('shop_code',$shop_code);
                })
                ->findOrEmpty();
            if($row->isExists()) return null;
        }
        return self::create([
            'ip'=>$ip,//获取用户IP地址
            'event_type'=>$event_type,
            'created_at'=>Carbon::now()->toDateTimeString(),
            'fbclid'=>Arr::get($request,'fbclid',''),
            'user_agent'=>Arr::get($request,'user_agent'),
            'website'=>Arr::get($request,'website'),
            'params'=>Arr::get($request,'params',[]),
            'is_track'=>ModelConstant::STATUS_OFF,
            'trace_id'=>'',
            "fbc_at"=>Arr::get($request,'fbc_at',0),
            'pid'=>0,
            'response'=> [],
            'product_id'=>$product_id,
            'order_id'=>Arr::get($request,'order_id',0),
            'platform'=>Arr::get($request,'platform',CommonConstant::TRAFFIC_SOURCE_FB),
            'shop_code'=>Arr::get($request,'shop_code','')
        ]);
    }


    public static function copyTrackLogs(PixelLogs $log, string $pixel_id)
    {
        $data = $log->toArray();
        $data['pid'] = $log->id;
        $data['pixel_id'] = $pixel_id;
        Arr::forget($data, 'id');
        return self::create($data);
    }

}
